package com.kingmed.kmss.framework.excel.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.kingmed.kmss.common.exception.BusinessException;
import com.kingmed.kmss.common.utils.JsonUtils;
import com.kingmed.kmss.framework.excel.ExcelListener;
import com.kingmed.kmss.framework.excel.ExcelResult;
import com.kingmed.kmss.framework.excel.handler.ExcelValidateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author liangzhi
 * @date 2023/6/15
 */
@Slf4j
public class ImportValidateListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {

    private final ExcelValidateHandler<T> validateHandler;
    private final Class<T> clz;
    private final List<String> errorMessageList;
    private List<T> dataList;
    private final Integer batchSize;
    private final String importBatchNo;

    public ImportValidateListener(ExcelValidateHandler<T> validateHandler, Class<T> clz, Integer batchSize, String importBatchNo) {
        this.validateHandler = validateHandler;
        this.clz = clz;
        this.errorMessageList = new ArrayList<>();
        dataList = new ArrayList<>(batchSize);
        this.batchSize = batchSize;
        this.importBatchNo = importBatchNo;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.debug("[{}]解析到一条表头数据: {}", context.readSheetHolder().getSheetName(), JsonUtils.toJsonString(headMap));
        this.validExcelHead(headMap);
    }

    @Override
    public ExcelResult<T> getExcelResult() {
        return null;
    }

    @Override
    public void invoke(T t, AnalysisContext analysisContext) {
        dataList.add(t);
        if (dataList.size() >= batchSize) {
            List<String> rowErrorMessageList = validateHandler.validateData(dataList, importBatchNo);
            if (CollectionUtils.isNotEmpty(rowErrorMessageList)) {
                errorMessageList.addAll(rowErrorMessageList);
            }
            dataList = new ArrayList<>(batchSize);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (CollectionUtils.isNotEmpty(dataList)) {
            List<String> rowErrorMessageList = validateHandler.validateData(dataList, importBatchNo);
            if (CollectionUtils.isNotEmpty(rowErrorMessageList)) {
                errorMessageList.addAll(rowErrorMessageList);
            }
        }
        log.info("校验完成");
    }

    public List<String> getErrorMessageList() {
        return errorMessageList;
    }

    public void validExcelHead(Map<Integer, String> headMap) {
        List<String> headList = new ArrayList<>();
        Class<?> clazz = clz;
        while (clazz != null) {
            Field[] fs = clazz.getDeclaredFields();
            for (Field feild : fs) {
                // 过滤没有数@ExcelProperty注解
                if (!feild.isAnnotationPresent(ExcelProperty.class)) {
                    continue;
                }
                ExcelProperty excelProperty = feild.getAnnotation(ExcelProperty.class);
                String[] value = excelProperty.value();
                headList.add(StringUtils.join(value));
            }
            clazz = clazz.getSuperclass();
        }
        List<String> errMsgList = new ArrayList<>();
        headMap.forEach((i, v) -> {
            if (!headList.contains(v)) {
                errMsgList.add(StrUtil.format("表头第{}列【{}】名称不符", i + 1, headMap.get(i)));
            }
        });
        if (CollectionUtils.isNotEmpty(errMsgList)) {
            throw new BusinessException("导入模板错误，请使用正确模板文件 {" + StrUtil.join(",", errMsgList) + "}");
        }
    }

}
